package cn.gov.msa.util;

import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis 工具类
 */
public class RedisUtils {
	private static Logger logger = Logger.getLogger(RedisUtils.class);

    protected static ReentrantLock lockPool = new ReentrantLock();

    public static JedisPool jedisPool = null;
    
    /**
     * 初始化Redis连接池
     */
    private static void initialPool() {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(Integer.parseInt(PropertiesTools.redisProperties("redis.maxActive")));
            config.setMaxIdle(Integer.parseInt(PropertiesTools.redisProperties("redis.maxIdle")));
            config.setMaxWaitMillis(Integer.parseInt(PropertiesTools.redisProperties("redis.maxWait")));
            config.setTestOnBorrow(Boolean.parseBoolean(PropertiesTools.redisProperties("redis.testOnBorrow")));
            String host = PropertiesTools.redisProperties("redis.host");
            int port =Integer.parseInt(PropertiesTools.redisProperties("redis.port"));
            int timeout = Integer.parseInt(PropertiesTools.redisProperties("redis.expiration"));
            jedisPool = new JedisPool(config, host, port,timeout);
        } catch (Exception e) {
        	logger.error("初始化连接池失败！",e);
        }
    }

    /**
     * 在多线程环境同步初始化，
     * redisPool只要一个就好了，所以要设置锁，保证只能初始化一个
     */
    private static void poolInit() {
        lockPool.lock();
        try {
            if (jedisPool == null) {
                initialPool();
            }
        } catch (Exception e) {
        	logger.error("初始化redis连接",e);
        } finally {
            lockPool.unlock();
        }
    }

    
    /**
     * 这里可以使用多线程进行加载，所以将锁去掉,
     * 保证了只有一个jedisPool，
     * @return
     */
    public static Jedis getJedis() {
        if (jedisPool == null) {
            poolInit();
        }
        Jedis jedis = null;
        try {
            if (jedisPool != null) {
                jedis = jedisPool.getResource();
            }
        } catch (Exception e) {
           logger.error("getJedis() 方法出错：" , e);
        } finally {
            close(jedis);
        }
        return jedis;
    }

    /**
     * 释放jedis资源
     * @param jedis
     */
    public static void close(final Jedis jedis) {
        try {
            if (jedis != null && jedisPool != null) {
                jedis.close();
            }
        } catch (Exception e) {
        	 logger.error("close() 方法出错：" , e);
        }
    }

    /**
     * 设置 String
     * 
     * @param key
     * @param value
     */
    public static boolean setString(String key, Object value) {
        try {
            getJedis().set(key.getBytes(), SerializeUtil.serialize(value));
            return true;
        } catch (Exception e) {
        	 logger.error("setString() 方法出错：key = " + key + "value = " + value , e);
            return false;
        }
    }

    /**
     * 设置 过期时间
     * 
     * @param key
     * @param seconds
     *            以秒为单位
     * @param value
     */
    public static boolean setString(String key, int seconds,Object value) {
        try {
            value = value==null? "" : value;
            getJedis().setex(key.getBytes(), seconds, SerializeUtil.serialize(value));
            return true;
        } catch (Exception e) {
        	logger.error("setString() 方法出错：" , e);
            return false;
        }
    }

    /**
     * 获取String值
     * 
     * @param key
     * @return value
     */
    public static Object getString(String key) {
        try {
            return SerializeUtil.unserialize(getJedis().get(key.getBytes()));
        } catch (Exception e) {
        	logger.error("getString() 方法出错： key = " + key, e );
            return "0$0";
        }
    }
    
    /**
     * 删除key的键值对
     * @param key
     * @return
     */
    public static boolean delString(String key){
        try {
            getJedis().del(key.getBytes());
            return true;
        } catch (Exception e) {
        	logger.error("getString() 方法出错： key = " + key , e  );
            return false;
        }
    }
}